﻿#region

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.ServiceModel.DomainServices.Server;
using System.Web;
using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.Barcodes;
using NetBay.Core.Log;
using NetBay.Core.Tools;
using Rio.Applications.Web.RioWCFServices;
using Rio.Doc.Business.Repository;

#endregion

namespace Rio.Applications.Web.Services
{
    public partial class BusinessEntitiesDomainService
    {
        #region Instance Methods

        /// <summary>
        ///   Adds the barcode.
        /// </summary>
        /// <param name="barcode"> The barcode. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnLong AddBarcode(Barcode barcode)
        {
            //Variable initialization.
            var l_oRet = new ReturnLong();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.AddBarcode (barcode <" + barcode + ">)...");

            try
            {
                l_oRet.Value = CABRepository.AddBarcode(barcode);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.AddBarcode Exception [" + ex.Message + "]");
                l_oRet = new ReturnLong("Exception in AddBarcode : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        /// Adds the barcode separator.
        /// </summary>
        /// <param name="serializeBarcodeSeparator">The p_o LST serialize barcode separator.</param>
        /// <returns></returns>
        [Query(HasSideEffects = true)]
        public IEnumerable<ReturnObject> AddBarcodeSeparatorList(string serializeBarcodeSeparator)
        {
            //Variable initialization.
            List<ReturnObject> l_oRet = new List<ReturnObject>();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.AddBarcodeSeparatorList (p_oLstSerializeBarcodeSeparator <" + serializeBarcodeSeparator + ">)...");

            //Deserialize List BarcodeSeparator object.
            List<BarcodeSeparator> p_oLstBarcodeSeparator = SerializationHelper.Deserialize<List<BarcodeSeparator>>(serializeBarcodeSeparator);

            try
            {
                foreach (BarcodeSeparator l_oBarCodeseparator in p_oLstBarcodeSeparator)
                {
                    LogManager.Instance().LogDebug("BarCodeDS.AddBarcodeSeparatorList (l_oBarCodeseparator<" + l_oBarCodeseparator + ">)...");
                    if (l_oBarCodeseparator.GetType() == typeof (BarcodeDocumentSeparator))
                    {
                        CABRepository.AddBarcodeDocumentSeparator(l_oBarCodeseparator as BarcodeDocumentSeparator);
                    }
                    else if (l_oBarCodeseparator.GetType() == typeof (BarcodeFolderSeparator))
                    {
                        CABRepository.AddBarcodeFolderSeparator(l_oBarCodeseparator as BarcodeFolderSeparator);
                    }
                }
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.AddBarcodeSeparatorList Exception [" + ex.Message + "]");
                ReturnObject l_oReturnObject = new ReturnObject(ex.Message);
                l_oRet.Add(l_oReturnObject);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Deletes the barcode.
        /// </summary>
        /// <param name="barcodeId"> The barcode id. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnBoolean DeleteBarcode(long barcodeId)
        {
            //Variable initialization.
            var l_oRet = new ReturnBoolean();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.DeleteBarcode (barcode <" + barcodeId.ToString() + ">)...");

            try
            {
                l_oRet.Value = CABRepository.DeleteBarcode(barcodeId);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.DeleteBarcode Exception [" + ex.Message + "]");
                l_oRet = new ReturnBoolean("Exception in DeleteBarcode : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Deletes the barcode List.
        /// </summary>
        /// <param name="p_sBarcodeIdList"> The barcode id List. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnBoolean DeleteBarcodeList(string p_sBarcodeIdList)
        {
            //Variable initialization.
            var l_oRet = new ReturnBoolean();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.DeleteBarcodeList (p_sBarcodeIdList <" + p_sBarcodeIdList + ">)...");

            try
            {
                l_oRet.Value = CABRepository.DeleteBarcodeList(p_sBarcodeIdList);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.DeleteBarcodeList Exception [" + ex.Message + "]");
                l_oRet = new ReturnBoolean("Exception in p_sBarcodeIdList : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Deletes the document barcode separator.
        /// </summary>
        /// <param name="barcodeId"> The identifier barcode. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnBoolean DeleteDocumentBarcodeSeparator(long barcodeId)
        {
            //Variable initialization.
            var l_oRet = new ReturnBoolean();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.DeleteDocumentBarcodeSeparator (barcodeId <" + barcodeId.ToString() + ">)...");

            try
            {
                l_oRet.Value = CABRepository.DeleteDocumentBarcodeSeparator(barcodeId);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.DeleteDocumentBarcodeSeparator Exception [" + ex.Message + "]");
                l_oRet = new ReturnBoolean("Exception in DeleteDocumentBarcodeSeparator : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Deletes the folder barcode separator.
        /// </summary>
        /// <param name="barcodeId"> The identifier barcode. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnBoolean DeleteFolderBarcodeSeparator(long barcodeId)
        {
            //Variable initialization.
            var l_oRet = new ReturnBoolean();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.DeleteFolderBarcodeSeparator (barcodeId <" + barcodeId.ToString() + ">)...");

            try
            {
                l_oRet.Value = CABRepository.DeleteFolderBarcodeSeparator(barcodeId);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.DeleteFolderBarcodeSeparator Exception [" + ex.Message + "]");
                l_oRet = new ReturnBoolean("Exception in DeleteFolderBarcodeSeparator : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Gets all barcodes.
        /// </summary>
        /// <returns> </returns>
        [Query(HasSideEffects = true)]
        public IEnumerable<Barcode> GetAllBarcodes(bool withEnabled = false)
        {
            //Variable initialization.
            var barcodes = new List<Barcode>();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.GetAllBarcodes (withEnabled <" + withEnabled.ToString() + ">)...");

            try
            {
                barcodes = CABRepository.GetBarcodes(withEnabled);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.GetAllBarcodes Exception [" + ex.Message + "]");
                barcodes.Add(new Barcode("Exception in GetAllBarcodes : " + ex.Message));
            }
            return barcodes;
        }

        /// <summary>
        ///   Gets all barcodes.
        /// </summary>
        /// <returns> </returns>
        [Query(HasSideEffects = true)]
        public IEnumerable<Barcode> GetAllTheBarCodes()
        {
            //Variable Initialization.
            var barcodes = new List<Barcode>();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.GetAllTheBarCodes (No parameters)...");

            try
            {
                barcodes = CABRepository.GetAllTheBarCodes();
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.GetAllTheBarCodes Exception [" + ex.Message + "]");
                barcodes.Add(new Barcode("Exception in GetAllTheBarCodes : " + ex.Message));
            }
            return barcodes;
        }

        /// <summary>
        ///   Retrieves the barcode separator id for paramCode.
        /// </summary>
        /// <param name="p_sBarcodeParamcode"> The Barcode Paramcode. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public long GetBarCodeId(string p_sBarcodeParamcode)
        {
            //Variable initiaalization.
            long l_oRet;

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.GetBarCodeId (p_sBarcodeParamcode <" + p_sBarcodeParamcode + ">)...");

            try
            {
                l_oRet = CABRepository.GetBarCodeId(p_sBarcodeParamcode);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.GetBarCodeId Exception [" + ex.Message + "]");
                l_oRet = 0;
            }
            return l_oRet;
        }

        /// <summary>
        ///   Gets the folder separator barcodes.
        /// </summary>
        /// <returns> </returns>
        [Query(HasSideEffects = true)]
        public IEnumerable<Barcode> GetFolderSeparatorBarcodes()
        {
            //Variable initialization.
            var barcodes = new List<Barcode>();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.GetAllBarcodes()...");

            try
            {
                barcodes = CABRepository.GetFolderSeparatorBarcodes();
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.GetFolderSeparatorBarcodes Exception [" + ex.Message + "]");
                barcodes.Add(new Barcode("Exception in GetFolderSeparatorBarcodes : " + ex.Message));
            }
            return barcodes;
        }

        /// <summary>
        ///   Runs the barcode processing on import files.
        /// </summary>
        /// <param name="images"> </param>
        /// <param name="organizationId"> The organization id. </param>
        /// <param name="folderTypeId"> The folder type id. </param>
        /// <param name="userId"> The user id. </param>
        /// <returns> </returns>
        [Query(HasSideEffects = true)]
        public IEnumerable<ImageRio> RunBarcodeProcessingOnImportFiles(List<string> images, long? organizationId, long? folderTypeId, long userId)
        {
            //Variable initialization.
            var l_oRet = new List<ImageRio>();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.RunBarcodeProcessingOnImportFiles (Nb docs: images <" + images.Count + ">, organizationId <" + organizationId + ">, folderTypeId <" + folderTypeId +
                                           ">, userId <" + userId + ">)...");

            try
            {
                //Get configured barcodes
                List<Barcode> rioBarcodes = new List<Barcode>(GetAllBarcodes(true));

                //Barcodes rio configured in the databases.
                if (rioBarcodes.Count > 0)
                {
                    //Do barcode recognition
                    DoBarcodeRecognitionResponse response;
                    using (WCFServiceClient L_oWCFServiceClient = new WCFServiceClient("BasicHttpBinding_IWCFService"))
                    {
                        DoBarcodeRecognitionRequest request = new DoBarcodeRecognitionRequest
                                                                  {
                                                                      p_lUserId = userId,
                                                                      images = images,
                                                                      p_bOrderByDescending = Convert.ToBoolean(ConfigurationManager.AppSettings["Rio.Applications.Import.OrderByDescending"]),
                                                                      p_oMessageRequest = new MessageRequest(ConfigurationManager.AppSettings.Get("LicenseKey"))
                                                                  };
                        request.p_oMessageRequest.EncryptLicense(RioApplicationSettings.LicenseKeyDuration);

                        response = L_oWCFServiceClient.DoBarcodeRecognition(request);
                    }

                    long? lastOrganizationId = organizationId;
                    long? lastFolderTypeId = folderTypeId;
                    foreach (var img in response.DoBarcodeRecognitionResult)
                    {
                        List<BarcodeSeparator> tempCb = new List<BarcodeSeparator>();
                        foreach (var barcode in img.OriginalBarcodes)
                        {
                            BarcodeSeparator bs = SearchBarcodeSeparator(rioBarcodes, barcode.Value, barcode.BarcodeType, organizationId, folderTypeId, lastOrganizationId, lastFolderTypeId);

                            if (bs != null)
                            {
                                // Tous les spérateurs de documents qui suivent ce barcode doivent être pour l'organisation et le td du separateur de dossier
                                if (bs.TypeOfBarcode == BarcodeSeparatorType.FolderSeparator && bs.OrganizationId > 0 && bs.FolderTypeId > 0)
                                {
                                    lastOrganizationId = bs.OrganizationId;
                                    lastFolderTypeId = bs.FolderTypeId;
                                }

                                tempCb.Add(bs);
                            }
                        }
                        img.SeparatorBarcodes = new List<BarcodeSeparator>(tempCb);
                    }

                    //Update foreign key.
                    l_oRet = response.DoBarcodeRecognitionResult;
                    foreach (var i in l_oRet)
                    {
                        foreach (var j in i.SeparatorBarcodes)
                        {
                            j.ForeignKey = i.Key;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogError("Exception in RunBarcodeProcessingOnImportFiles : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Update the barcode.
        /// </summary>
        /// <param name="barcode"> The barcode. </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnLong UpdateBarcode(Barcode barcode)
        {
            //Variable initialization.
            var l_oRet = new ReturnLong();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.UpdateBarcode (barcode <" + barcode + ">)...");

            try
            {
                l_oRet.Value = CABRepository.UpdateBarcode(barcode);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.UpdateBarcode Exception [" + ex.Message + "]");
                l_oRet = new ReturnLong("Exception in UpdateBarcode : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        ///   Update the barcode status List.
        /// </summary>
        /// <param name="p_sBarcodeIdList"> The barcode id List. </param>
        /// <param name="p_bBarCodeStatus"> The Barcode status to update </param>
        /// <returns> </returns>
        [Invoke(HasSideEffects = true)]
        public ReturnBoolean UpdateStatusBarcodeList(string p_sBarcodeIdList, Boolean p_bBarCodeStatus)
        {
            //Variable initialization.
            var l_oRet = new ReturnBoolean();

            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.UpdateStatusBarcodeList (p_sBarcodeIdList <" + p_sBarcodeIdList + ">, (p_bBarCodeStatus <" + p_bBarCodeStatus.ToString() + ">)...");

            try
            {
                l_oRet.Value = CABRepository.UpdateStatusBarcodeList(p_sBarcodeIdList, p_bBarCodeStatus);
            }
            catch (Exception ex)
            {
                //Error.
                LogManager.Instance().LogError("BarCodeDS.UpdateStatusBarcodeList Exception [" + ex.Message + "]");
                l_oRet = new ReturnBoolean("Exception in p_sBarcodeIdList : " + ex.Message);
            }
            return l_oRet;
        }

        /// <summary>
        /// Gets the barcode by value.
        /// </summary>
        /// <param name="barcodes">The barcodes.</param>
        /// <param name="value">The value.</param>
        /// <param name="bcType">Type of the bc.</param>
        /// <param name="originalOrganizationId">The original organization id.</param>
        /// <param name="originalFolderTypeId">The original folder type id.</param>
        /// <param name="organizationId">The organization id.</param>
        /// <param name="folderTypeId">The folder type id.</param>
        /// <returns></returns>
        private BarcodeSeparator SearchBarcodeSeparator(List<Barcode> barcodes, string value, BarcodeType bcType, long? originalOrganizationId, long? originalFolderTypeId, long? organizationId,
                                                        long? folderTypeId)
        {
            //Log.
            LogManager.Instance().LogDebug("BarCodeDS.SearchBarcodeSeparator (Nb barcodes: <" + barcodes.Count + ">, organizationId <" + organizationId + ">, folderTypeId <" + folderTypeId +
                                           ">, value <" + value + ">, , bcType <" + bcType + ">...)");
            try
            {
                // hard-coded --> Daphne, CG13
                try
                {
                    string fileName = Path.Combine(HttpContext.Current.Server.MapPath("~/bin"), "RioWebBarcode.csv");
                    if (File.Exists(fileName))
                    {
                        Dictionary<string, string> dictionary =
                            File.ReadLines(fileName).Select(line => line.Split(','))
                                .
                                ToDictionary(line => line[0], line => line[1]).Where(p => p.Key == value)
                                .ToDictionary(p => p.Key, p => p.Value);
                        if (dictionary.Count > 0)
                        {
                            value = dictionary.First().Value;
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Instance().LogError("Exception in SearchBarcodeSeparator - Daphne : " + ex.Message);
                }

                // Here we take the first part of the barcode, ex: NBY001 (<prefix><Paramcode>)
                string prefix = value.Substring(0, 3);
                string paramCode = value.Substring(3, 3);

                //Retrieves barcode on the database.
                List<Barcode> l_oBarcodeActive = CABRepository.GetBarcodes(true);

                //Find good barcode.
                var foundBarcodes = l_oBarcodeActive.Find(p => p.Prefix == prefix && p.ParamCode == paramCode && p.Type == bcType);

                //Return good barcode separator list.
                if (foundBarcodes != null)
                {
                    if (foundBarcodes.Function == BarcodeSeparatorType.DocumentSeparator && organizationId.HasValue && folderTypeId.HasValue)
                    {
                        //Take paramcode of the current barcode param. 
                        string subParameterCode = value.Substring(6, 3);
                        foreach (var item in foundBarcodes.BarCodeSeparatorList)
                        {
                            if (((BarcodeDocumentSeparator) item).ParamCode == subParameterCode
                                && item.TypeOfBarcode == BarcodeSeparatorType.DocumentSeparator
                                && item.OrganizationId == organizationId
                                && item.FolderTypeId == folderTypeId)
                            {
                                item.BarcodeName = foundBarcodes.Name;
                                return item;
                            }
                        }
                    }
                    else if (foundBarcodes.Function == BarcodeSeparatorType.FolderSeparator)
                    {
                        //Get index value on the barcode
                        string indexValue = value.Substring(6);
                        if (indexValue == string.Empty)
                        {
                            //tohack: Folder separator without correspondence are not implemented !!

                            foundBarcodes.BarCodeSeparatorList[0].BarcodeName = foundBarcodes.Name;
                            return foundBarcodes.BarCodeSeparatorList[0];
                        }
                        else
                        {
                            foreach (var item in foundBarcodes.BarCodeSeparatorList)
                            {
                                //barcode with correspondence
                                if (item.TypeOfBarcode == BarcodeSeparatorType.FolderSeparator
                                    && item.OrganizationId != 0
                                    && item.FolderTypeId != 0)
                                {
                                    //only if no folderty or organization selected or if the the selected org and flodertype is equal to the correspondence
                                    //if ((item.OrganizationId == originalOrganizationId && item.FolderTypeId == originalFolderTypeId)
                                    //    || (originalOrganizationId == null && originalFolderTypeId == null))
                                    //{
                                        ((BarcodeFolderSeparator) item).RecognizedIndexValue = indexValue;
                                        Dictionary<long, string> indexIdValue = new Dictionary<long, string>
                                                                                    {
                                                                                        {
                                                                                            Convert.ToInt64(((BarcodeFolderSeparator) item).UniqueIndexIdentifier),
                                                                                            ((BarcodeFolderSeparator) item).RecognizedIndexValue
                                                                                            },
                                                                                    };
                                        //add unicity result
                                        var isUnique = IndexRepository.CheckUnicityOfIndexValue(item.FolderTypeId, indexIdValue, -1);
                                        ((BarcodeFolderSeparator) item).RecognizedUniqueIndexValue = isUnique.Count != 0;
                                        item.BarcodeName = foundBarcodes.Name;
                                        return item;
                                    //}
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogError("Exception in SearchBarcodeSeparator : " + ex.Message);
            }

            return null;
        }

        #endregion
    }
}